package com.vinfai.reflection;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.TreeMap;

import org.apache.log4j.Logger;

public class ReflectionClass {
	
	private static final Logger logger = Logger.getLogger(ReflectionClass.class);
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		//getAllFields(ReflectObj.class, true);
		ReflectObj obj = new ReflectObj();
		//Object val = getFieldValue(obj, "strs");
		//logger.info(val);
		methodInvoke(obj, "add",new Object[]{10,20});
		
		getConstructInfo(obj, new Object[]{new Long(101),"HELLO WORLD!"});
	
		operArray();
	}
	
	
	
	public static Field[] getAllFields(Class clazz,boolean isDeclared){
		if(isDeclared){
			Field[] fields = clazz.getDeclaredFields();
			for(Field field : fields){
				String modifier = Modifier.toString(field.getModifiers());
				logger.info("字段修饰符："+modifier+"  "+field.getType().getName()+"  "+ field.getName());
				//返回一个描述此 Field（包括其一般类型）的字符串
				//eg: public static final int java.lang.Thread.MIN_PRIORITY
				logger.info(field.toGenericString());
			}
		}
		return null;
	}
	/**
	 * 获得某个字段的值
	 * @param clazz 
	 * @param isFull 是否返回全类名
	 * @return 类型，字符串形式
	 */
	private static  Object getFieldValue(Object obj,String fieldName){
		try {
			Class clazz = obj.getClass();
			//Field field = clazz.getField(fieldName);
			Field field = clazz.getDeclaredField(fieldName);
			if(!field.isAccessible()){
				field.setAccessible(true);
			}
			StringBuffer _val = new StringBuffer();
			Object val = field.get(obj);
			if(field.getType().isArray()){
				//一维数据可以，二维以上就不知道如何处理了
				int len = Array.getLength(val);
				for(int i=0;i<len;i++){
					_val.append(Array.get(val, i).toString());
					if(i!=len-1){
						_val.append(",");
					}
				}
				val = _val;
			}
			
			//设置字段值方法：
//			field.setInt(obj, 100);
			return val;
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	
	//方法调用
	public static  void methodInvoke(Object obj,String methodName,Object[] params){
		Class clazz = obj.getClass();
		Method[] methods = clazz.getDeclaredMethods();
		for(Method method : methods){
			if(method.getName().equals(methodName)){
				//方法名称、参数等信息
				logger.info("方法 :"+method.toString());
				logger.info("方法名称："+method.getName());
				logger.info("参数类型："+method.getParameterTypes());
				Class[] parcls = method.getParameterTypes();
				for(Class cls : parcls){
					logger.info("param # " +cls);
				}
				logger.info("返回值类型："+method.getReturnType());
				//异常
				Class[] execls = method.getExceptionTypes();
				for(Class cls : execls){
					logger.info("exception # " +cls);
				}
				try {
					Object rs = method.invoke(obj, params);
					logger.info("结果："+rs);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	
	public static void getConstructInfo(Object obj,Object[] params){
		Class clazz =  obj.getClass();
		Constructor[] constors = clazz.getDeclaredConstructors();
//		clazz.getDeclaredConstructor(params);
		for(Constructor cons : constors){
			logger.info(cons.toGenericString());
			logger.info("constructor parameter types :");
			Class[] pcls = cons.getParameterTypes();
			for(Class cls : pcls){
				logger.info("param #："+cls);
			}
		}
	
		//通过构造方法创建对象
		try {
			Class[] paramTypes = new Class[]{Long.class,String.class};
			Constructor cons1 = clazz.getDeclaredConstructor(null);
			Constructor cons2 = clazz.getDeclaredConstructor(paramTypes);
			ReflectObj robj = (ReflectObj)cons1.newInstance();
			logger.info("value is "+robj.get_log()+";"+robj.get_str());
			
			ReflectObj robj2 = (ReflectObj)cons2.newInstance(params);
			logger.info("value2 is "+robj2.get_log()+" ; "+robj2.get_str());
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	/**
	 * 数组相关操作
	 * 
	 */
	public  static void operArray() throws Exception{
		//创建数组，并赋值
		Class clazz = Class.forName("java.lang.String");
		Object arr = Array.newInstance(clazz, 10);
		Array.set(arr, 5, "HELLO WORLD!");
		Object obj = Array.get(arr, 5);
		logger.info("return value is "+obj);
		
		//创建多维数组
		int[] dims = new int[]{5,6,10};
		Object arr2 = Array.newInstance(String.class, dims);
		Object arrobj1 = Array.get(arr, 1);
		Object arrobj2 = Array.get(arrobj1, 2);
		Array.set(arrobj2, 5, "HELLO WORLD!");
		String[][][] strs = (String[][][])arr2;
		logger.info(strs[1][2][5]);
	}
}
